package util

import (
	"io"

	"github.com/pkg/errors"
	"k8s.io/kubernetes/cmd/kubeadm/app/util/runtime"
	utilsexec "k8s.io/utils/exec"
)

type ContainerInterface interface {
	util.ContainerRuntime
	RunContainer(image, command string, args, mounts, dockerArgs []string, writer io.Writer) error
}

// CRIRuntime is a struct that interfaces with the CRI
type CRIRuntime struct {
	util.ContainerRuntime
	exec utilsexec.Interface
}

// DockerRuntime is a struct that interfaces with the Docker daemon
type DockerRuntime struct {
	util.ContainerRuntime
	exec utilsexec.Interface
}

// NewContainerRuntime sets up and returns a ContainerRuntime struct
func NewContainerRuntime(execer utilsexec.Interface, criSocket string) (ContainerInterface, error) {
	runtime, err := util.NewContainerRuntime(execer, criSocket)

	switch runtime.(type) {
	case *util.CRIRuntime:
		return &CRIRuntime{runtime, execer}, err
	case *util.DockerRuntime:
		return &DockerRuntime{runtime, execer}, err
	default:
		return nil, err
	}
}

// Docker Run Images for container if the image exists on the system
func (runtime *CRIRuntime) RunContainer(image, command string, args, mounts, dockerArgs []string, writer io.Writer) error {
	return errors.New("CRIRuntime: Not Suppost")
}

// Docker Run Images for container if the image exists on the system
func (runtime *DockerRuntime) RunContainer(image, command string, args, mounts, dockerArgs []string, writer io.Writer) error {
	runArgs := append([]string{"run"}, dockerArgs...)
	for _, mount := range mounts {
		runArgs = append(runArgs, "-v", mount)
	}
	runArgs = append(runArgs, image, command)
	runArgs = append(runArgs, args...)

	var cmd = runtime.exec.Command("docker", runArgs...)
	cmd.SetStderr(writer)
	cmd.SetStdout(writer)

	return cmd.Run()
}